/**
 * 画箭头
 * @param {*} fromX
 * @param {*} fromY
 * @param {*} toX
 * @param {*} toY
 * @param {*} theta
 * @param {*} headlen
 * @param {*} width
 * @param {*} color
 */

let index = 1;
class DrawArrow {
    constructor(props) {
        this.id = `DrawArrow_${index++}`;
        this.type = 'DrawArrow';
        this.props = props;
        this.render = this.render.bind(this);
        this.computePath = this.computePath.bind(this);
        const canvas = document.getElementById("canvas");
        this.ctx = canvas.getContext("2d");
        const { fromX, fromY, toX, toY } = this.props;
        this.fromX = fromX;
        this.fromY = fromY;
        this.toX = toX;
        this.toY = toY;
        this.width = 100;
        this.height = 100;
        this.startElement = null;
        this.endElement = null;
        this.direction = 0; // 箭头初始方向， 0 1 2 3 ： 上 右 下 左
    }
    render() {
        let step = 30;
        this.ctx.moveTo(this.fromX, this.fromY);
        this.computePath(this.fromX, this.fromY, 1, this.direction);
    }
    drug(x1, y1, x2, y2) {
        this.fromX = x1 || this.fromX;
        this.fromY = y1 || this.fromY;
        this.toX = x2 || this.toX;
        this.toY = y2 || this.toY;
    }
    /**
     * 递归路线计算
     * @param {*} x1
     * @param {*} y1
     * @param {*} x2
     * @param {*} y2
     * @param {*} index
     */
    computePath(x, y, index, direction) {
        function obliqueX() {
            let x3 = x, y3 = y + (this.toY - y) / 2;
            this.ctx.lineTo(x3, y3);
            x1 = this.toX
            y1 = y3;
            this.ctx.stroke();
        }

        function obliqueY() {
            let x3 = x + (this.toX - x) / 2, y3 = y;
            this.ctx.lineTo(x3, y3);
            x1 = x3
            y1 = this.toY;
            this.ctx.stroke();
        }
        index++;
        if (x === this.toX && y === this.toY) return;
        // console.log("第几次递归：", index++);
        if (index > 5) {
            console.log("算法异常");
            return false;
        }
        let rato = (this.toY - y) / (this.toX - x);
        let x1, y1;
        let next = () => {
            this.ctx.lineTo(x1, y1);
            this.ctx.stroke();
            this.drawArrow(x1, y1, this.toX, this.toY);
        };
        let repeat = (x, y) => {
            this.ctx.lineTo(x, y);
            this.ctx.stroke();
            this.computePath(x, y, index, direction);
        };
        // 上
        if (direction === 0) {
            if (this.toY <= y) {
                // 判断修改箭头方向
                if (Math.abs(this.toY - y) > Math.abs(this.toX - x)) {
                    obliqueX.call(this)
                } else {
                    x1 = x;
                    y1 = this.toY;

                }
                next();
            } else {
                let offset =
                    index === 2 ? this.width / 2 + 30 : this.height + 60;
                offset = index <= 3 ? offset : 0;
                let step = this.toX > x ? offset : -offset;
                direction = this.toX > x ? 1 : 3;

                if (index === 2) {
                    y = y - 30;
                    this.ctx.lineTo(x, y);
                    this.ctx.stroke();
                }
                repeat(x + step, y);
            }
        } else if (direction === 1) {
            if (this.toX >= x) {
                if (Math.abs(this.toX - x) > Math.abs(this.toY - y)) {
                    obliqueY.call(this)
                } else {
                    // 常规
                    x1 = this.toX;
                    y1 = y;
                }
                next();
            } else {
                let offset =
                    index === 2 ? this.height / 2 + 30 : this.width + 60;
                offset = index <= 3 ? offset : 0;
                let step = this.toY > y ? offset : -offset;
                direction = this.toY > y ? 2 : 0;
                if (index === 2) {
                    x = x + 30;
                    this.ctx.lineTo(x, y);
                    this.ctx.stroke();
                }
                repeat(x, y + step);
            }
        } else if (direction === 2) {
            if (this.toY >= y) {
                if (Math.abs(this.toY - y) > Math.abs(this.toX - x)) {
                    obliqueX.call(this)
                } else {
                    // 常规
                    x1 = x;
                    y1 = this.toY;
                }
                next();
            } else {
                let offset =
                    index === 2 ? this.width / 2 + 30 : this.height + 60;
                offset = index <= 3 ? offset : 0;
                let step = this.toX > x ? offset : -offset;
                direction = this.toX > x ? 1 : 3;
                if (index === 2) {
                    y = y + 30;
                    this.ctx.lineTo(x, y);
                    this.ctx.stroke();
                }
                repeat(x + step, y);
            }
        } else if (direction === 3) {
            if (this.toX <= x) {
                if (Math.abs(this.toX - x) > Math.abs(this.toY - y)) {
                    obliqueY.call(this)
                } else {
                    // 常规
                    x1 = this.toX;
                    y1 = y;
                }
                next();
            } else {
                let offset =
                    index === 2 ? this.height / 2 + 30 : this.width + 60;
                offset = index <= 3 ? offset : 0;
                let step = this.toY > y ? offset : -offset;
                direction = this.toY > y ? 2 : 0;
                if (index === 2) {
                    x = x - 30;
                    this.ctx.lineTo(x, y);
                    this.ctx.stroke();
                }
                repeat(x, y + step);
            }
        }
    }

    drawArrow(fromX, fromY, toX, toY) {
        // console.log("方向：", this.direction)
        const {
            theta = 30,
            headlen = 10,
            width = 2,
            color = "0f0",
        } = this.props;

        // 计算各角度和对应的P2,P3坐标
        var angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
            angle1 = ((angle + theta) * Math.PI) / 180,
            angle2 = ((angle - theta) * Math.PI) / 180,
            topX = headlen * Math.cos(angle1),
            topY = headlen * Math.sin(angle1),
            botX = headlen * Math.cos(angle2),
            botY = headlen * Math.sin(angle2);

        this.ctx.save();
        this.ctx.beginPath();

        var arrowX = fromX - topX,
            arrowY = fromY - topY;

        this.ctx.moveTo(arrowX, arrowY);
        this.ctx.moveTo(fromX, fromY);
        this.ctx.lineTo(toX, toY);
        arrowX = toX + topX;
        arrowY = toY + topY;
        this.ctx.moveTo(arrowX, arrowY);
        this.ctx.lineTo(toX, toY);
        arrowX = toX + botX;
        arrowY = toY + botY;
        this.ctx.lineTo(arrowX, arrowY);
        this.ctx.strokeStyle = color;
        this.ctx.lineWidth = width;
        this.ctx.stroke();
        // ctx.restore();
    }
}

export default DrawArrow;
